home *** CD-ROM | disk | FTP | other *** search
/ AmigActive 10 / AACD 10.iso / AACD / Games / MAME / src / vidhrdw / thunderj.c < prev    next >
C/C++ Source or Header  |  2000-04-04  |  31KB  |  1,069 lines

  1. /***************************************************************************
  2.  
  3.   vidhrdw/thunderj.c
  4.  
  5.   Functions to emulate the video hardware of the machine.
  6.  
  7. ****************************************************************************
  8.  
  9.     Playfield encoding
  10.     ------------------
  11.         1 16-bit word is used
  12.  
  13.         Word 1:
  14.             Bits 13-15 = palette
  15.             Bits  0-12 = image number
  16.  
  17.  
  18.     Motion Object encoding
  19.     ----------------------
  20.         4 16-bit words are used
  21.  
  22.         Word 1:
  23.             Bits  0-9  = link to the next motion object
  24.  
  25.         Word 2:
  26.             Bits  0-14 = image index
  27.  
  28.         Word 3:
  29.             Bits  7-15 = horizontal position
  30.             Bits  0-3  = motion object palette
  31.  
  32.         Word 4:
  33.             Bits  7-15 = vertical position
  34.             Bits  4-6  = horizontal size of the object, in tiles
  35.             Bit   3    = horizontal flip
  36.             Bits  0-2  = vertical size of the object, in tiles
  37.  
  38.  
  39.     Alpha layer encoding
  40.     --------------------
  41.         1 16-bit word is used
  42.  
  43.         Word 1:
  44.             Bit  15    = transparent/opaque
  45.             Bit  10-13 = color
  46.             Bits  0-9  = index of the character
  47.  
  48. ***************************************************************************/
  49.  
  50. #include "driver.h"
  51. #include "machine/atarigen.h"
  52. #include "vidhrdw/generic.h"
  53.  
  54. #define XCHARS 42
  55. #define YCHARS 30
  56.  
  57. #define XDIM (XCHARS*8)
  58. #define YDIM (YCHARS*8)
  59.  
  60.  
  61. #define DEBUG_VIDEO 0
  62.  
  63.  
  64.  
  65. /*************************************
  66.  *
  67.  *    Structures
  68.  *
  69.  *************************************/
  70.  
  71. struct pf_overrender_data
  72. {
  73.     struct osd_bitmap *bitmap;
  74.     int mo_priority;
  75. };
  76.  
  77.  
  78.  
  79. /*************************************
  80.  *
  81.  *    Statics
  82.  *
  83.  *************************************/
  84.  
  85. static struct atarigen_pf_state pf_state;
  86. static struct atarigen_pf_state pf2_state;
  87.  
  88. static UINT16 alpha_bank;
  89. static UINT16 palette_bank;
  90. static UINT32 *start_end;
  91.  
  92. #if DEBUG_VIDEO
  93. static UINT8 show_colors;
  94. static UINT8 special_pen;
  95. #endif
  96.  
  97.  
  98.  
  99. /*************************************
  100.  *
  101.  *    Prototypes
  102.  *
  103.  *************************************/
  104.  
  105. static const UINT8 *update_palette(void);
  106.  
  107. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  108. static void pf2_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  109. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  110. static void pf2_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  111. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  112. static void pf2_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *data);
  113.  
  114. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  115. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param);
  116.  
  117. #if DEBUG_VIDEO
  118. static void debug(void);
  119. #endif
  120.  
  121.  
  122.  
  123. /*************************************
  124.  *
  125.  *    Video system start
  126.  *
  127.  *************************************/
  128.  
  129. int thunderj_vh_start(void)
  130. {
  131.     static struct atarigen_mo_desc mo_desc =
  132.     {
  133.         1024,                /* maximum number of MO's */
  134.         8,                   /* number of bytes per MO entry */
  135.         2,                   /* number of bytes between MO words */
  136.         0,                   /* ignore an entry if this word == 0xffff */
  137.         0, 0, 0x3ff,         /* link = (data[linkword] >> linkshift) & linkmask */
  138.         1                    /* reverse order */
  139.     };
  140.  
  141.     static struct atarigen_pf_desc pf_desc =
  142.     {
  143.         8, 8,                /* width/height of each tile */
  144.         64, 64                /* number of tiles in each direction */
  145.     };
  146.     
  147.     /* reset statics */
  148.     memset(&pf_state, 0, sizeof(pf_state));
  149.     memset(&pf2_state, 0, sizeof(pf2_state));
  150.     
  151.     /* allocate memory */
  152.     start_end = malloc(sizeof(UINT32) * 512);
  153.     if (!start_end)
  154.         return 1;
  155.     
  156.     /* initialize the playfield */
  157.     if (atarigen_pf_init(&pf_desc))
  158.     {
  159.         free(start_end);
  160.         return 1;
  161.     }
  162.     
  163.     /* initialize the second playfield */
  164.     if (atarigen_pf2_init(&pf_desc))
  165.     {
  166.         atarigen_pf_free();
  167.         free(start_end);
  168.         return 1;
  169.     }
  170.     
  171.     /* initialize the motion objects */
  172.     if (atarigen_mo_init(&mo_desc))
  173.     {
  174.         atarigen_pf2_free();
  175.         atarigen_pf_free();
  176.         free(start_end);
  177.         return 1;
  178.     }
  179.     
  180.     return 0;
  181. }
  182.  
  183.  
  184.  
  185. /*************************************
  186.  *
  187.  *    Video system shutdown
  188.  *
  189.  *************************************/
  190.  
  191. void thunderj_vh_stop(void)
  192. {
  193.     atarigen_pf2_free();
  194.     atarigen_pf_free();
  195.     atarigen_mo_free();
  196.     if (start_end)
  197.         free(start_end);
  198.     start_end = NULL;
  199. }
  200.  
  201.  
  202.  
  203. /*************************************
  204.  *
  205.  *    Alpha banking
  206.  *
  207.  *************************************/
  208.  
  209. void thunderj_set_alpha_bank(int bank)
  210. {
  211.     alpha_bank = bank * 0x200;
  212. }
  213.  
  214.  
  215.  
  216. /*************************************
  217.  *
  218.  *    Playfield RAM write handlers
  219.  *
  220.  *************************************/
  221.  
  222. WRITE_HANDLER( thunderj_colorram_w )
  223. {
  224.     int oldword = READ_WORD(&atarigen_playfieldram_color[offset]);
  225.     int newword = COMBINE_WORD(oldword, data);
  226.  
  227.     /* only update if changed */
  228.     if (oldword != newword)
  229.     {
  230.         WRITE_WORD(&atarigen_playfieldram_color[offset], newword);
  231.         
  232.         oldword ^= newword;
  233.         
  234.         /* low byte affects pf1 */
  235.         if (oldword & 0x00ff)
  236.             atarigen_pf_dirty[(offset / 2) & 0xfff] = 1;
  237.  
  238.         /* upper byte affects pf2 */
  239.         if (oldword & 0xff00)
  240.             atarigen_pf2_dirty[(offset / 2) & 0xfff] = 1;
  241.     }
  242. }
  243.  
  244.  
  245. WRITE_HANDLER( thunderj_playfieldram_w )
  246. {
  247.     int oldword = READ_WORD(&atarigen_playfieldram[offset]);
  248.     int newword = COMBINE_WORD(oldword, data);
  249.  
  250.     /* only update if changed */
  251.     if (oldword != newword)
  252.     {
  253.         WRITE_WORD(&atarigen_playfieldram[offset], newword);
  254.         atarigen_pf_dirty[(offset / 2) & 0xfff] = 1;
  255.     }
  256.     
  257.     /* handle the latch, but only write the lower byte */
  258.     if (atarigen_video_control_state.latch2 != -1)
  259.         thunderj_colorram_w(offset, atarigen_video_control_state.latch2 | 0xff000000);
  260. }
  261.  
  262.  
  263. WRITE_HANDLER( thunderj_playfield2ram_w )
  264. {
  265.     int oldword = READ_WORD(&atarigen_playfield2ram[offset]);
  266.     int newword = COMBINE_WORD(oldword, data);
  267.  
  268.     /* only update if changed */
  269.     if (oldword != newword)
  270.     {
  271.         WRITE_WORD(&atarigen_playfield2ram[offset], newword);
  272.         atarigen_pf2_dirty[(offset / 2) & 0xfff] = 1;
  273.     }
  274.     
  275.     /* handle the latch, but only write the upper byte */
  276.     if (atarigen_video_control_state.latch1 != -1)
  277.         thunderj_colorram_w(offset, atarigen_video_control_state.latch1 | 0x00ff0000);
  278. }
  279.  
  280.  
  281.  
  282. /*************************************
  283.  *
  284.  *    Scroll register parser
  285.  *
  286.  *************************************/
  287.  
  288. static void recompute_scrolls_and_update(int scanline)
  289. {
  290.     /* copy in the scroll values */
  291.     pf_state.hscroll = atarigen_video_control_state.pf1_xscroll + (atarigen_video_control_state.pf2_xscroll & 7);
  292.     pf_state.vscroll = atarigen_video_control_state.pf1_yscroll;
  293.     pf2_state.hscroll = atarigen_video_control_state.pf2_xscroll + 4;
  294.     pf2_state.vscroll = atarigen_video_control_state.pf2_yscroll;
  295.     
  296.     /* update the two playfields */
  297.     atarigen_pf_update(&pf_state, scanline);
  298.     atarigen_pf2_update(&pf2_state, scanline);
  299. }
  300.  
  301.  
  302.  
  303. /*************************************
  304.  *
  305.  *    Periodic scanline updater
  306.  *
  307.  *************************************/
  308.  
  309. void thunderj_scanline_update(int scanline)
  310. {
  311.     /* update the playfield */
  312.     if (scanline == 0)
  313.     {
  314.         int new_bank;
  315.         
  316.         atarigen_video_control_update(&atarigen_alpharam[0xf00]);
  317.         recompute_scrolls_and_update(scanline);
  318.  
  319.         /* check for a new palette bank */
  320.         new_bank = atarigen_video_control_state.palette_bank * 0x400;
  321.         if (new_bank != palette_bank)
  322.         {
  323.             palette_bank = new_bank;
  324.             memset(atarigen_pf2_dirty, 0xff, atarigen_playfieldram_size / 2);
  325.         }
  326.     }
  327.     
  328.     /* update the MOs from the SLIP table */
  329.     atarigen_mo_update_slip_512(atarigen_spriteram, atarigen_video_control_state.sprite_yscroll, scanline, &atarigen_alpharam[0xf80]);
  330. }
  331.  
  332.  
  333.  
  334. /*************************************
  335.  *
  336.  *    Main refresh
  337.  *
  338.  *************************************/
  339.  
  340. void thunderj_vh_screenrefresh(struct osd_bitmap *bitmap,int full_refresh)
  341. {
  342.     int i;
  343.     
  344. #if DEBUG_VIDEO
  345.     debug();
  346. #endif
  347.  
  348.     /* update the palette */
  349.     if (update_palette())
  350.     {
  351.         memset(atarigen_pf_dirty, 1, atarigen_playfieldram_size / 2);
  352.         memset(atarigen_pf2_dirty, 1, atarigen_playfield2ram_size / 2);
  353.     }
  354.  
  355.     /* set up the all-transparent overrender palette */
  356.     for (i = 0; i < 16; i++)
  357.         atarigen_overrender_colortable[i] = palette_transparent_pen;
  358.  
  359.     /* render the playfield */
  360.     memset(atarigen_pf_visit, 0, 64*64);
  361. #if DEBUG_VIDEO
  362.     if (show_colors == 2)
  363.         osd_clearbitmap(bitmap);
  364.     else
  365. #endif
  366.     atarigen_pf_process(pf_render_callback, bitmap, &Machine->drv->visible_area);
  367.  
  368.     /* render the playfield */
  369.     memset(atarigen_pf2_visit, 0, 64*64);
  370. #if DEBUG_VIDEO
  371.     if (show_colors != 1)
  372. #endif
  373.     atarigen_pf2_process(pf2_render_callback, bitmap, &Machine->drv->visible_area);
  374.  
  375.     /* render the motion objects */
  376.     memset(start_end, 0xff, 512 * sizeof(UINT32));
  377.     atarigen_mo_process(mo_render_callback, bitmap);
  378.     
  379.     /* redraw the alpha layer completely */
  380.     {
  381.         const struct GfxElement *gfx = Machine->gfx[2];
  382.         int sx, sy, offs;
  383.  
  384.         for (sy = 0; sy < YCHARS; sy++)
  385.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  386.             {
  387.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  388.                 int code = data & 0x1ff;
  389.                 int opaque = data & 0x8000;
  390.     
  391.                 if (data & 0x200) code += alpha_bank;
  392.                 if (code || opaque)
  393.                 {
  394.                     int color = ((data >> 10) & 0xf) | ((data >> 9) & 0x20);
  395.                     drawgfx(bitmap, gfx, code, color, 0, 0, 8 * sx, 8 * sy, 0,
  396.                             opaque ? TRANSPARENCY_NONE : TRANSPARENCY_PEN, 0);
  397.                 }
  398.             }
  399.     }
  400.  
  401.     /* update onscreen messages */
  402.     atarigen_update_messages();
  403. }
  404.  
  405.  
  406.  
  407. /*************************************
  408.  *
  409.  *    Palette management
  410.  *
  411.  *************************************/
  412.  
  413. static const UINT8 *update_palette(void)
  414. {
  415.     UINT16 mo_map[16], al_map[64], pf_map[32];
  416.     int i, j;
  417.  
  418.     /* reset color tracking */
  419.     memset(mo_map, 0, sizeof(mo_map));
  420.     memset(pf_map, 0, sizeof(pf_map));
  421.     memset(al_map, 0, sizeof(al_map));
  422.     palette_init_used_colors();
  423.     
  424.     /* update color usage for the playfields */
  425.     atarigen_pf_process(pf_color_callback, pf_map, &Machine->drv->visible_area);
  426.     atarigen_pf2_process(pf2_color_callback, pf_map, &Machine->drv->visible_area);
  427.  
  428.     /* update color usage for the mo's */
  429.     atarigen_mo_process(mo_color_callback, mo_map);
  430.  
  431.     /* update color usage for the alphanumerics */
  432.     {
  433.         const unsigned int *usage = Machine->gfx[2]->pen_usage;
  434.         int sx, sy, offs;
  435.  
  436.         for (sy = 0; sy < YCHARS; sy++)
  437.             for (sx = 0, offs = sy * 64; sx < XCHARS; sx++, offs++)
  438.             {
  439.                 int data = READ_WORD(&atarigen_alpharam[offs * 2]);
  440.                 int color = ((data >> 10) & 0xf) | ((data >> 9) & 0x20);
  441.                 int code = data & 0x1ff;
  442.     
  443.                 if (data & 0x200) code += alpha_bank;
  444.                 al_map[color] |= usage[code];
  445.             }
  446.     }
  447.  
  448.     /* rebuild the playfield palettes */
  449.     for (i = 0; i < 16; i++)
  450.     {
  451.         UINT16 used = pf_map[i];
  452.         if (used)
  453.         {
  454.             if (palette_bank == 0 || i == 0)
  455.                 palette_used_colors[0x200 + palette_bank + i * 16] = PALETTE_COLOR_TRANSPARENT;
  456.             else if (used & 0x0001)
  457.                 palette_used_colors[0x200 + palette_bank + i * 16] = PALETTE_COLOR_USED;
  458.             for (j = 1; j < 16; j++)
  459.                 if (used & (1 << j))
  460.                     palette_used_colors[0x200 + palette_bank + i * 16 + j] = PALETTE_COLOR_USED;
  461.         }
  462.     }
  463.     for (i = 16; i < 32; i++)
  464.     {
  465.         UINT16 used = pf_map[i];
  466.         if (used)
  467.             for (j = 0; j < 16; j++)
  468.                 if (used & (1 << j))
  469.                     palette_used_colors[0x200 + i * 16 + j] = PALETTE_COLOR_USED;
  470.     }
  471.  
  472.     /* rebuild the motion object palette */
  473.     for (i = 0; i < 16; i++)
  474.     {
  475.         UINT16 used = mo_map[i];
  476.         if (used)
  477.         {
  478.             palette_used_colors[0x100 + palette_bank + i * 16 + 0] = PALETTE_COLOR_TRANSPARENT;
  479.             for (j = 1; j < 16; j++)
  480.                 if (used & (1 << j))
  481.                     palette_used_colors[0x100 + palette_bank + i * 16 + j] = PALETTE_COLOR_USED;
  482.         }
  483.     }
  484.  
  485.     /* rebuild the alphanumerics palette */
  486.     for (i = 0; i < 64; i++)
  487.     {
  488.         UINT16 used = al_map[i];
  489.         if (used)
  490.             for (j = 0; j < 4; j++)
  491.                 if (used & (1 << j))
  492.                     palette_used_colors[0x000 + i * 4 + j] = PALETTE_COLOR_USED;
  493.     }
  494.  
  495.     return palette_recalc();
  496. }
  497.  
  498.  
  499.  
  500. /*************************************
  501.  *
  502.  *    Playfield palette
  503.  *
  504.  *************************************/
  505.  
  506. static void pf_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  507. {
  508.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  509.     UINT16 *colormap = param;
  510.     int x, y;
  511.     
  512.     /* standard loop over tiles */
  513.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  514.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  515.         {
  516.             int offs = x * 64 + y;
  517.             int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  518.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  519.             int code = data1 & 0x7fff;
  520.             int color = 0x10 + (data2 & 0x0f);
  521.  
  522.             /* mark the colors used by this tile */
  523.             colormap[color] |= usage[code];
  524.             
  525.             /* also mark unvisited tiles dirty */
  526.             if (!atarigen_pf_visit[offs]) atarigen_pf_dirty[offs] = 1;
  527.         }
  528. }
  529.  
  530.  
  531. static void pf2_color_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  532. {
  533.     const unsigned int *usage = Machine->gfx[0]->pen_usage;
  534.     UINT16 *colormap = param;
  535.     int x, y;
  536.     
  537.     /* standard loop over tiles */
  538.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  539.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  540.         {
  541.             int offs = x * 64 + y;
  542.             int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  543.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  544.             int code = data1 & 0x7fff;
  545.             int color = (data2 >> 8) & 0x0f;
  546.  
  547.             /* mark the colors used by this tile */
  548.             colormap[color] |= usage[code];
  549.             
  550.             /* also mark unvisited tiles dirty */
  551.             if (!atarigen_pf2_visit[offs]) atarigen_pf2_dirty[offs] = 1;
  552.         }
  553. }
  554.  
  555.  
  556.  
  557. /*************************************
  558.  *
  559.  *    Playfield rendering
  560.  *
  561.  *************************************/
  562.  
  563. static void pf_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  564. {
  565.     const struct GfxElement *gfx = Machine->gfx[0];
  566.     struct osd_bitmap *bitmap = param;
  567.     int x, y;
  568.  
  569.     /* standard loop over tiles */
  570.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  571.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  572.         {
  573.             int offs = x * 64 + y;
  574.             
  575.             /* update only if dirty */
  576.             if (atarigen_pf_dirty[offs])
  577.             {
  578.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  579.                 int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  580.                 int color = 0x10 + (data2 & 0x0f);
  581.                 int code = data1 & 0x7fff;
  582.                 int hflip = data1 & 0x8000;
  583.                 
  584.                 drawgfx(atarigen_pf_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  585.                 atarigen_pf_dirty[offs] = 0;
  586.  
  587. #if DEBUG_VIDEO
  588.                 if (show_colors == 1 || show_colors == -1)
  589.                 {
  590.                     char c;
  591.                     if (show_colors == 1)
  592.                         c = "0123456789ABCDEF"[(data2 >> 4) & 0x0f];
  593.                     else
  594.                         c = "0123456789ABCDEF"[(data2 >> 0) & 0x0f];
  595.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  596.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  597.                     drawgfx(atarigen_pf_bitmap, Machine->uifont, c, 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  598.                 }
  599. #endif
  600.             }
  601.             
  602.             /* track the tiles we've visited */
  603.             atarigen_pf_visit[offs] = 1;
  604.         }
  605.  
  606.     /* then blast the result */
  607.     x = -state->hscroll;
  608.     y = -state->vscroll;
  609.     copyscrollbitmap(bitmap, atarigen_pf_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_NONE, 0);
  610. }
  611.  
  612.  
  613. static void pf2_render_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  614. {
  615.     const struct GfxElement *gfx = Machine->gfx[0];
  616.     struct osd_bitmap *bitmap = param;
  617.     int x, y;
  618.  
  619.     /* standard loop over tiles */
  620.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  621.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  622.         {
  623.             int offs = x * 64 + y;
  624.             
  625.             /* update only if dirty */
  626.             if (atarigen_pf2_dirty[offs])
  627.             {
  628.                 int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  629.                 int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  630.                 int color = (data2 >> 8) & 0x0f;
  631.                 int code = data1 & 0x7fff;
  632.                 int hflip = data1 & 0x8000;
  633.  
  634.                 color += palette_bank >> 4;
  635.                 
  636.                 drawgfx(atarigen_pf2_bitmap, gfx, code, color, hflip, 0, 8 * x, 8 * y, 0, TRANSPARENCY_NONE, 0);
  637.                 atarigen_pf2_dirty[offs] = 0;
  638.  
  639. #if DEBUG_VIDEO
  640.                 if (show_colors == 2 || show_colors == -2)
  641.                 {
  642.                     char c;
  643.                     if (show_colors == 2)
  644.                         c = "0123456789ABCDEF"[(data2 >> 12) & 0x0f];
  645.                     else
  646.                         c = "0123456789ABCDEF"[(data2 >> 8) & 0x0f];
  647.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 0, 8 * y, 0, TRANSPARENCY_PEN, 0);
  648.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 1, 0, 0, 8 * x + 2, 8 * y, 0, TRANSPARENCY_PEN, 0);
  649.                     drawgfx(atarigen_pf2_bitmap, Machine->uifont, c, 0, 0, 0, 8 * x + 1, 8 * y, 0, TRANSPARENCY_PEN, 0);
  650.                 }
  651. #endif
  652.             }
  653.             
  654.             /* track the tiles we've visited */
  655.             atarigen_pf2_visit[offs] = 1;
  656.         }
  657.  
  658.     /* then blast the result */
  659.     x = -state->hscroll;
  660.     y = -state->vscroll;
  661.     copyscrollbitmap(bitmap, atarigen_pf2_bitmap, 1, &x, 1, &y, clip, TRANSPARENCY_PEN, palette_transparent_pen);
  662. }
  663.  
  664.  
  665.  
  666. /*************************************
  667.  *
  668.  *    Playfield overrendering
  669.  *
  670.  *************************************/
  671.  
  672. static const UINT16 transparency_mask[4] = { 0xffff, 0x00ff, 0x00ff, 0x00ff };
  673.  
  674. static void pf_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  675. {
  676.     const struct pf_overrender_data *overrender_data = param;
  677.  
  678.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  679.     const struct GfxElement *gfx = Machine->gfx[0];
  680.     int mo_priority = overrender_data->mo_priority;
  681.     int x, y;
  682.  
  683.     /* standard loop over tiles */
  684.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  685.     {
  686.         int sx = (8 * x - state->hscroll) & 0x1ff;
  687.         if (sx >= XDIM) sx -= 0x200;
  688.  
  689.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  690.         {
  691.             int offs = x * 64 + y;
  692.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  693.             int priority = (data2 >> 4) & 3;
  694.             
  695.             if (priority > mo_priority)
  696.             {
  697.                 int color = 0x10 + (data2 & 0x0f);
  698.                 int data1 = READ_WORD(&atarigen_playfieldram[offs * 2]);
  699.                 int code = data1 & 0x7fff;
  700.                 int hflip = data1 & 0x8000;
  701.  
  702.                 int sy = (8 * y - state->vscroll) & 0x1ff;
  703.                 if (sy >= YDIM) sy -= 0x200;
  704.  
  705.                 if (mo_priority == -1)
  706.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  707. #if DEBUG_VIDEO
  708.                 else if (special_pen != -1)
  709.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, ~(1 << special_pen));
  710. #endif
  711.                 else
  712.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, transparency_mask[priority]);
  713.             }
  714.         }
  715.     }
  716. }
  717.  
  718.  
  719. static void pf2_overrender_callback(const struct rectangle *clip, const struct rectangle *tiles, const struct atarigen_pf_state *state, void *param)
  720. {
  721.     const struct pf_overrender_data *overrender_data = param;
  722.  
  723.     struct osd_bitmap *bitmap = overrender_data->bitmap;
  724.     const struct GfxElement *gfx = Machine->gfx[0];
  725.     int mo_priority = overrender_data->mo_priority;
  726.     int x, y;
  727.  
  728.     /* standard loop over tiles */
  729.     for (x = tiles->min_x; x != tiles->max_x; x = (x + 1) & 63)
  730.     {
  731.         int sx = (8 * x - state->hscroll) & 0x1ff;
  732.         if (sx >= XDIM) sx -= 0x200;
  733.  
  734.         for (y = tiles->min_y; y != tiles->max_y; y = (y + 1) & 63)
  735.         {
  736.             int offs = x * 64 + y;
  737.             int data2 = READ_WORD(&atarigen_playfieldram_color[offs * 2]);
  738.             int priority = (data2 >> 12) & 3;
  739.             
  740.             if (priority > mo_priority)
  741.             {
  742.                 int color = (data2 >> 8) & 0x0f;
  743.                 int data1 = READ_WORD(&atarigen_playfield2ram[offs * 2]);
  744.                 int code = data1 & 0x7fff;
  745.                 int hflip = data1 & 0x8000;
  746.  
  747.                 int sy = (8 * y - state->vscroll) & 0x1ff;
  748.                 if (sy >= YDIM) sy -= 0x200;
  749.  
  750.                 color += palette_bank >> 4;
  751.             
  752.                 if (mo_priority == -1)
  753.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  754. #if DEBUG_VIDEO
  755.                 else if (special_pen != -1)
  756.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, ~(1 << special_pen));
  757. #endif
  758.                 else
  759.                     drawgfx(bitmap, gfx, code, color, hflip, 0, sx, sy, clip, TRANSPARENCY_PENS, transparency_mask[priority]);
  760.             }
  761.         }
  762.     }
  763. }
  764.  
  765.  
  766.  
  767. /*************************************
  768.  *
  769.  *    Motion object palette
  770.  *
  771.  *************************************/
  772.  
  773. static void mo_color_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  774. {
  775.     const unsigned int *usage = Machine->gfx[1]->pen_usage;
  776.     UINT16 *colormap = param;
  777.     int code = data[1] & 0x7fff;
  778.     int color = data[2] & 0x000f;
  779.     int hsize = ((data[3] >> 4) & 7) + 1;
  780.     int vsize = (data[3] & 7) + 1;
  781.     int tiles = hsize * vsize;
  782.     UINT16 temp = 0;
  783.     int i;
  784.  
  785.     for (i = 0; i < tiles; i++)
  786.         temp |= usage[code++];
  787.     colormap[color] |= temp;
  788. }
  789.  
  790.  
  791.  
  792. /*************************************
  793.  *
  794.  *    Motion object rendering
  795.  *
  796.  *************************************/
  797.  
  798. static void mo_render_callback(const UINT16 *data, const struct rectangle *clip, void *param)
  799. {
  800.     struct GfxElement *gfx = Machine->gfx[1];
  801.     struct pf_overrender_data overrender_data;
  802.     struct osd_bitmap *bitmap = param;
  803.     struct rectangle pf_clip;
  804.  
  805.     /* extract data from the various words */
  806.     int hflip = data[1] & 0x8000;
  807.     int code = data[1] & 0x7fff;
  808.     int xpos = (data[2] >> 7) - atarigen_video_control_state.sprite_xscroll;
  809.     int priority = (data[2] >> 4) & 3;
  810.     int special = (data[2] >> 6) & 1;
  811.     int color = data[2] & 0x000f;
  812.     int ypos = -(data[3] >> 7) - atarigen_video_control_state.sprite_yscroll;
  813.     int hsize = ((data[3] >> 4) & 7) + 1;
  814.     int vsize = (data[3] & 7) + 1;
  815.  
  816.     color += palette_bank >> 4;
  817.  
  818.     /* adjust for height */
  819.     ypos -= vsize * 8;
  820.  
  821.     /* adjust the final coordinates */
  822.     xpos &= 0x1ff;
  823.     ypos &= 0x1ff;
  824.     if (xpos >= XDIM) xpos -= 0x200;
  825.     if (ypos >= YDIM) ypos -= 0x200;
  826.  
  827.     /* determine the bounding box */
  828.     atarigen_mo_compute_clip_8x8(pf_clip, xpos, ypos, hsize, vsize, clip);
  829.     
  830.     /* special case? */
  831.     if (special)
  832.     {
  833.         UINT32 temp = start_end[ypos & 0x1ff];
  834.         UINT32 start = temp >> 16;
  835.         UINT32 stop = temp & 0xffff;
  836.         
  837.         /* update the data */
  838.         if (code == 2)
  839.             start = xpos & 0x1ff;
  840.         else if (code == 4)
  841.             stop = xpos & 0x1ff;
  842.         start_end[ypos & 0x1ff] = (start << 16) | stop;
  843.         
  844.         /* render if complete */
  845.         if (start != 0xffff && stop != 0xffff)
  846.         {
  847.             struct rectangle temp_clip = *clip;
  848.             int x;
  849.             
  850.             /* adjust coordinates */
  851.             if (start >= XDIM) start -= 0x200;
  852.             if (start > stop) stop += 0x200;
  853.  
  854.             /* set up a clipper */
  855.             temp_clip.min_x = (start < temp_clip.min_x) ? temp_clip.min_x : start;
  856.             temp_clip.max_x = (stop > temp_clip.max_x) ? temp_clip.max_x : stop;
  857.             
  858.             /* draw it */
  859.             for (x = start; x < stop; x += 8)
  860.             {
  861.                 atarigen_mo_draw_8x8(bitmap, gfx, 2, color, hflip, 0, x, ypos, 1, 1, (&temp_clip), TRANSPARENCY_PEN, 0);
  862.             }
  863.             start_end[ypos & 0x1ff] = 0xffffffff;
  864.         }
  865.     }
  866.  
  867.     /* simple case? */
  868.     else if (priority == 3)
  869.     {
  870.         /* just draw -- we have dominion over all */
  871.         atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  872.     }
  873.  
  874. #if DEBUG_VIDEO
  875.     else if (show_colors)
  876.     {
  877.         atarigen_mo_draw_8x8(bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  878.     }
  879. #endif
  880.  
  881.     /* otherwise, it gets a smidge trickier */
  882.     else
  883.     {
  884.         /* draw an instance of the object in all transparent pens */
  885.         atarigen_mo_draw_transparent_8x8(bitmap, gfx, code, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PEN, 0);
  886.  
  887.         /* and then draw it normally to the temp bitmap */
  888.         atarigen_mo_draw_8x8(atarigen_pf_overrender_bitmap, gfx, code, color, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_NONE, 0);
  889.  
  890.         /* overrender the playfields on top of that */
  891.         overrender_data.mo_priority = priority;
  892.         overrender_data.bitmap = atarigen_pf_overrender_bitmap;
  893.         atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  894.         atarigen_pf2_process(pf2_overrender_callback, &overrender_data, &pf_clip);
  895.  
  896.         /* special case the special pens */
  897.         if (priority == 0 && (color & 0x0f) == 0)
  898.         {
  899.             /* draw an instance of the object's pen 1 in transparent pen */
  900.             atarigen_mo_draw_transparent_8x8(atarigen_pf_overrender_bitmap, gfx, code, hflip, 0, xpos, ypos, hsize, vsize, clip, TRANSPARENCY_PENS, 0xfffd);
  901.     
  902.             /* overrender the playfields into those regions */
  903.             /* note: the reversed order is intentional */
  904.             overrender_data.mo_priority = -1;
  905.             atarigen_pf2_process(pf2_overrender_callback, &overrender_data, &pf_clip);
  906.             atarigen_pf_process(pf_overrender_callback, &overrender_data, &pf_clip);
  907.         }
  908.  
  909.         /* finally, copy this chunk to the real bitmap */
  910.         copybitmap(bitmap, atarigen_pf_overrender_bitmap, 0, 0, 0, 0, &pf_clip, TRANSPARENCY_THROUGH, palette_transparent_pen);
  911.     }
  912.  
  913. #if DEBUG_VIDEO
  914.     if (show_colors)
  915.     {
  916.         int tx = (pf_clip.min_x + pf_clip.max_x) / 2 - 3;
  917.         int ty = (pf_clip.min_y + pf_clip.max_y) / 2 - 4;
  918.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  919.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty - 2, 0, TRANSPARENCY_NONE, 0);
  920.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx - 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  921.         drawgfx(bitmap, Machine->uifont, ' ', 0, 0, 0, tx + 2, ty + 2, 0, TRANSPARENCY_NONE, 0);
  922.         drawgfx(bitmap, Machine->uifont, "0123456789ABCDEF"[priority], 0, 0, 0, tx, ty, 0, TRANSPARENCY_NONE, 0);
  923.     }
  924. #endif
  925. }
  926.  
  927.  
  928.  
  929. /*************************************
  930.  *
  931.  *    Debugging
  932.  *
  933.  *************************************/
  934.  
  935. #if DEBUG_VIDEO
  936.  
  937. static void debug(void)
  938. {
  939.     int new_show_colors;
  940.     
  941.     new_show_colors = (keyboard_pressed(KEYCODE_LSHIFT)) ? 1 : keyboard_pressed(KEYCODE_RSHIFT) ? 2 : 0;
  942.     if (new_show_colors)
  943.         if (keyboard_pressed(KEYCODE_LCONTROL) || keyboard_pressed(KEYCODE_RCONTROL))
  944.             new_show_colors = -new_show_colors;
  945.     
  946.     if (new_show_colors != show_colors)
  947.     {
  948.         show_colors = new_show_colors;
  949.         memset(atarigen_pf_dirty, 0xff, atarigen_playfieldram_size / 2);
  950.         memset(atarigen_pf2_dirty, 0xff, atarigen_playfieldram_size / 2);
  951.     }
  952.  
  953.     special_pen = -1;
  954.     if (keyboard_pressed(KEYCODE_Q)) special_pen = 0;
  955.     if (keyboard_pressed(KEYCODE_W)) special_pen = 1;
  956.     if (keyboard_pressed(KEYCODE_E)) special_pen = 2;
  957.     if (keyboard_pressed(KEYCODE_R)) special_pen = 3;
  958.     if (keyboard_pressed(KEYCODE_T)) special_pen = 4;
  959.     if (keyboard_pressed(KEYCODE_Y)) special_pen = 5;
  960.     if (keyboard_pressed(KEYCODE_U)) special_pen = 6;
  961.     if (keyboard_pressed(KEYCODE_I)) special_pen = 7;
  962.  
  963.     if (keyboard_pressed(KEYCODE_A)) special_pen = 8;
  964.     if (keyboard_pressed(KEYCODE_S)) special_pen = 9;
  965.     if (keyboard_pressed(KEYCODE_D)) special_pen = 10;
  966.     if (keyboard_pressed(KEYCODE_F)) special_pen = 11;
  967.     if (keyboard_pressed(KEYCODE_G)) special_pen = 12;
  968.     if (keyboard_pressed(KEYCODE_H)) special_pen = 13;
  969.     if (keyboard_pressed(KEYCODE_J)) special_pen = 14;
  970.     if (keyboard_pressed(KEYCODE_K)) special_pen = 15;
  971.     
  972.     if (keyboard_pressed(KEYCODE_9))
  973.     {
  974.         static int count;
  975.         char name[50];
  976.         FILE *f;
  977.         int i;
  978.  
  979.         while (keyboard_pressed(KEYCODE_9)) { }
  980.  
  981.         sprintf(name, "Dump %d", ++count);
  982.         f = fopen(name, "wt");
  983.  
  984.         fprintf(f, "\n\nAlpha Palette:\n");
  985.         for (i = 0x000; i < 0x100; i++)
  986.         {
  987.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  988.             if ((i & 15) == 15) fprintf(f, "\n");
  989.         }
  990.  
  991.         fprintf(f, "\n\nMotion Object Palette:\n");
  992.         for (i = 0x100; i < 0x200; i++)
  993.         {
  994.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  995.             if ((i & 15) == 15) fprintf(f, "\n");
  996.         }
  997.  
  998.         fprintf(f, "\n\nPlayfield Palette:\n");
  999.         for (i = 0x200; i < 0x400; i++)
  1000.         {
  1001.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  1002.             if ((i & 15) == 15) fprintf(f, "\n");
  1003.         }
  1004.  
  1005.         fprintf(f, "\n\nAlpha Palette 2:\n");
  1006.         for (i = 0x400; i < 0x500; i++)
  1007.         {
  1008.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  1009.             if ((i & 15) == 15) fprintf(f, "\n");
  1010.         }
  1011.  
  1012.         fprintf(f, "\n\nMotion Object Palette 2:\n");
  1013.         for (i = 0x500; i < 0x600; i++)
  1014.         {
  1015.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  1016.             if ((i & 15) == 15) fprintf(f, "\n");
  1017.         }
  1018.  
  1019.         fprintf(f, "\n\nPlayfield Palette 2:\n");
  1020.         for (i = 0x600; i < 0x800; i++)
  1021.         {
  1022.             fprintf(f, "%04X ", READ_WORD(&paletteram[i*2]));
  1023.             if ((i & 15) == 15) fprintf(f, "\n");
  1024.         }
  1025.  
  1026.         fprintf(f, "\n\nMotion Objects\n");
  1027.         for (i = 0; i < 0x400; i++)
  1028.         {
  1029.             UINT16 *data = (UINT16 *)&atarigen_spriteram[i*8];
  1030.             int hflip = data[1] & 0x8000;
  1031.             int code = data[1] & 0x7fff;
  1032.             int xpos = (data[2] >> 7);
  1033.             int priority = (data[2] >> 4) & 7;
  1034.             int color = data[2] & 0x000f;
  1035.             int ypos = (data[3] >> 7);
  1036.             int hsize = ((data[3] >> 4) & 7) + 1;
  1037.             int vsize = (data[3] & 7) + 1;
  1038.             fprintf(f, "   Object %03X: L=%03X P=%04X C=%X X=%03X Y=%03X W=%d H=%d F=%d LEFT=(%04X %04X %04X %04X)\n",
  1039.                     i, data[0] & 0x3ff, code, color, xpos & 0x1ff, ypos & 0x1ff, hsize, vsize, hflip,
  1040.                     data[0] & 0xfc00, data[1] & 0x0000, data[2] & 0x0070, data[3] & 0x0000);
  1041.         }
  1042.  
  1043.         fprintf(f, "\n\nPlayfield 1 dump\n");
  1044.         for (i = 0; i < atarigen_playfieldram_size / 2; i++)
  1045.         {
  1046.             fprintf(f, "%X%04X ", READ_WORD(&atarigen_playfieldram_color[i*2]) & 0xff, READ_WORD(&atarigen_playfieldram[i*2]));
  1047.             if ((i & 63) == 63) fprintf(f, "\n");
  1048.         }
  1049.  
  1050.         fprintf(f, "\n\nPlayfield 2 dump\n");
  1051.         for (i = 0; i < atarigen_playfield2ram_size / 2; i++)
  1052.         {
  1053.             fprintf(f, "%X%04X ", (READ_WORD(&atarigen_playfieldram_color[i*2]) >> 8) & 0xff, READ_WORD(&atarigen_playfield2ram[i*2]));
  1054.             if ((i & 63) == 63) fprintf(f, "\n");
  1055.         }
  1056.  
  1057.         fprintf(f, "\n\nAlpha dump\n");
  1058.         for (i = 0; i < atarigen_alpharam_size / 2; i++)
  1059.         {
  1060.             fprintf(f, "%04X ", READ_WORD(&atarigen_alpharam[i*2]));
  1061.             if ((i & 63) == 63) fprintf(f, "\n");
  1062.         }
  1063.  
  1064.         fclose(f);
  1065.     }
  1066. }
  1067.  
  1068. #endif
  1069.